/* rtpSigLibP.h - private RTP signal library header */

/*
 * Copyright (c) 2003-2005 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use
 * of this software may be licensed only pursuant to the terms
 * of an applicable Wind River license agreement.
 */

/*
modification history
--------------------
01m,11may05,gls  added OBJ_HANDLE to rtpChildWait() (SPR #109170)
                 added rtpChildIdGet() (SPR #106428)
                 added rtpChildHandleGet() (SPR #109349)
		 updated copyright notice
01l,29sep04,ans  added _rtpSigqueue ()
01k,24sep04,ans  Added RTP_TASK_MINI_SIG_CB to RTP_SIG_CB
01j,18may04,ans  alternate signal stack support.
01i,17may04,ans  added parent signal mask inheritance support.
01h,11feb04,ans  added support for sigwait() related calls.
01g,01dec03,nrj  coding std changes
01f,25nov03,nrj  code review mods
01e,27oct03,nrj  added support for waitpid
01d,22oct03,nrj  added extern defs for API
01c,16oct03,nrj  added syscall state save in sigctx
01b,15oct03,nrj  added extern decl and fixed sigsuspend mask issue
01a,11oct03,nrj  created.
*/

#ifndef	__INCrtpSigLibPh
#define	__INCrtpSigLibPh

#ifdef	_ASMLANGUAGE
#else	/* _ASMLANGUAGE */

#ifdef __cplusplus
extern "C" {
#endif

/* includes */

#include "vxWorks.h"
#include "sigLib.h"
#include "dllLib.h"
#include "private/sigLibP.h"

/* macros */

/*
 * Following macros are used by Signal delivery mechanism.
 * When signal is delivered (carving user handler ctx) these
 * macros values are stored with saved ctx. When the Sig handler
 * returns, One of these is set and return takes action further on.
 */

#define		SIG_DELIVERED_IN_WINDCTX	0x0000
#define		SIG_DELIVERED_IN_EXCEPTION	0x0010
#define		SIG_DELIVERED_IN_SYSCALL	0x0100
#define		SIG_DELIVERED_SYSCALL_RESTART	0x0001
#define		SIG_DELIVERED_WITH_SYSCALL_RESTART         \
			(SIG_DELIVERED_IN_SYSCALL |        \
			SIG_DELIVERED_SYSCALL_RESTART)

/*
 * Following macros are used when task wishes to wait for
 * a child RTP to die or wait for some signal.
 * When task initiates wait for signal/child it is added to the
 * wait List with RTP control block.
 * When a signal arrives, the task is woken
 * up and based on these macro value, it is unqueued from RTP
 */

#define         SIG_TASK_NOT_QUEUED             0
#define         SIG_TASK_QUEUED_SIGWAIT         1
#define         SIG_TASK_QUEUED_CHILDWAIT       2
#define         SIG_TASK_QUEUED_SYNCSIG         3

/* typedefs */

/* To deliver a RTP signal we do following
 * a) Save the current context
 * b) create new context to run user-mode signal handler
 * c) Resume to new context and run sig handler
 * d) After signal handler finishes Resume to saved context
 *
 * Following sigctx is used in step (a) and (d). The mem for
 * this is allocated from tasks's User-mode stack.
 */

typedef struct rtpSigCtx
    {
    int                 type;           /* one of above macros */
    REG_SET             regs;           /* Processor context for a task */
    sigset_t            savedMask;      /* mask prior to sig-handler */
    siginfo_t           info;           /* signal info, passed to handlr */
    int                 args[8];        /* args of intrptd syscall */
    int                 scn;            /* intrptd syscall number */
    } RTP_SIG_CTX;

/*
 * The signal can be generated for RTP and task . So both have
 * signal control blocks in addition to their own control 
 * block.
 * The Signal control block (SIG_CB) for both share some
 * common properties and differ in some other.
 * For signal-internal users like timer/IO/child-die, it is desired
 * to provide uniform interface. (see sigpend struct in sigLibP.h)
 * Sigpend data struct and TCB only provides one "pointer" to for
 * Signal-Control-block. Signal lib internally cast these pointer as
 * per its own allocated data struct (SIG_CB).
 */

typedef enum rtpTcbCmnType 
    {
    SIG_CB_TCB,
    SIG_CB_RTP
    } RTP_TCB_CMN_TYPE;


typedef struct rtpTaskMiniSigCb
   {
   BOOL                 isSigCbInitialized;
   sigset_t             parentSigMask;
   } RTP_TASK_MINI_SIG_CB;
 
/*
 * Common data struct for RTP and Task SIGnal control block
 */

typedef struct rtpSigTcbRtpCmn
    {
    /* sigMini should be the first item of this structure */

    RTP_TASK_MINI_SIG_CB sigMini;                        /* minimal signal CB */
    DL_NODE		cmnRtpSigWaitNode;		/* node for tasks */
    struct sigq		cmnSigQHead[_NSIGS + 1];	/* qed signals */
    sigset_t		cmnKillSigs;			/* which kill sigs */
    sigset_t		cmnQueuedSigs;			/* if qed, which */
    RTP_TCB_CMN_TYPE	cmnRtpOrTcb;			/* is it RTP or TCB */
    union
	{
	struct wind_rtp	* pRtpId;
	WIND_TCB	* pTid;
        } cmnOwnerId;

#define sigCmnRtpId cmnOwnerId.pRtpId
#define sigCmnTid cmnOwnerId.pTid

    } RTP_SIG_TCB_RTP_CMN;

/*
 * RTP signal control block.
 * static part of WIND_RTP & not allocated dynamically
 */

typedef struct rtpSigCB
    {
    /* sigCmnControlBlock should be the first item of this structure */

    RTP_SIG_TCB_RTP_CMN	sigCmnControlBlock;
    struct sigaction	sigVector[_NSIGS + 1];	/* Sigaction user handlers */
    struct sigpend	* pSigQ;		/* pool for Sigqueue */
    } RTP_SIG_CB;

typedef struct sigwait_
    {
    sigset_t            waitsigs;               /* wait signal mask */
    siginfo_t           waitinfo;               /* wait signal info */
    } SIG_WAIT;

/*
 * TASK signal control block.
 * "pTcb->pSignalInfo "
 *
 * IMPORTANT - do not confuse it with **Kernel task's** sigtcb
 *
 * NOTE that for kernel task pSignalInfo--> points to sigtcb
 * and for RTP task pSignalInfo--> points to rtpsigtcb
 * It is allocated dynamically only when required.
 */

typedef struct rtpTaskSigCB
    {
    /* sigCmnControlBlock should be the first item of this structure */

    RTP_SIG_TCB_RTP_CMN	sigCmnControlBlock;	/* common part of SIG_CB */
    sigset_t		blockedSigs;		/* Mask of Task */
    sigset_t		savedBlockedSigs;	/* temp storage for mask */
    INT32		qState;			/* qued for sig/child */
    int			nestedCount;		/* sanity check sigreturn */
    SIG_WAIT          * pSigwait;               /* task signal wait info */
    struct wind_rtp   * childRtpId;		/* child rtpId to wait for */
    stack_t             signalStack;            /* alternate signal stack */
    } RTP_TASK_SIG_CB;

/*
 * struct sigpend is defined in sigLibP.h, it is used by many services
 * including timer, posix message, aio drivers ...
 * We use the same struct for easy porting of those services
 * to RTP universe.
 */

typedef struct sigpend RTP_SIG_PEND;

/*
 * For ease of source code reading 
 */

#define sigQHead	sigCmnControlBlock.cmnSigQHead
#define killSigs	sigCmnControlBlock.cmnKillSigs
#define queuedSigs	sigCmnControlBlock.cmnQueuedSigs
#define rtpOrTcb	sigCmnControlBlock.cmnRtpOrTcb
#define sigCBRtpId	sigCmnControlBlock.cmnOwnerId.pRtpId
#define sigCBTid	sigCmnControlBlock.cmnOwnerId.pTid
#define rtpSigwaitNode	sigCmnControlBlock.cmnRtpSigWaitNode


/* externs */

/* exported functionality - not all are system call */

extern int rtpSigaction (int, const struct sigaction *,
					struct sigaction *, void *);
extern int rtpSigprocmask (int, const sigset_t *, sigset_t *);
extern int rtpSigaltstack (const stack_t * , stack_t *);
extern int rtpSigpending (sigset_t *);
extern int rtpSigsuspend (const sigset_t *);
extern int rtpPause ();
extern int rtpTaskKill (WIND_TCB *, int);
extern int rtpTaskSigqueue (WIND_TCB *, int, const union sigval);
extern int _rtpTaskSigqueue (WIND_TCB *, int, const union sigval, int sigCode);
extern int rtpTaskSigPendKill (WIND_TCB *, struct sigpend *);
extern int rtpKill (RTP_ID,  int);
extern int rtpSigqueue (RTP_ID,  int, const union sigval);
extern int _rtpSigqueue (RTP_ID,  int, const union sigval, int sigCode);
extern int rtpSigPendKill (RTP_ID,  struct sigpend *);
extern STATUS rtpSigPendInit (struct sigpend *);
extern STATUS rtpSigPendDestroy (struct sigpend *);
extern void rtpSigReturn (void);
extern OBJ_HANDLE rtpChildHandleGet (RTP_ID);
extern RTP_ID rtpChildIdGet (OBJ_HANDLE);
extern RTP_ID rtpChildWait (RTP_ID, OBJ_HANDLE *, int *, int);
extern int rtpSigtimedwait (const sigset_t *pSet, struct siginfo *pInfo,
                            const struct timespec *pTimeout);
extern int rtpSigwaitinfo (const sigset_t *pSet, struct siginfo *pInfo);
extern int rtpSigwait (const sigset_t *pSet, int *pSig);



#ifdef __cplusplus
}
#endif

#endif	/* _ASMLANGUAGE */

#endif	/* __INCrtpSigLibPh */
